#ifndef T_AVCODEC_H
#define T_AVCODEC_H

#include "stable.h"

class T_AVImage
{
public:
    virtual enum PixelFormat pix_fmt() = 0;
    virtual int width() = 0;
    virtual int height() = 0;
    virtual uint8_t **data() = 0;
    virtual int *linesize() = 0;
};

class T_AVFrame : public T_AVImage
{
protected:
    AVCodecContext *m_codec_ctx;
    AVFrame *m_frame;
public:
    explicit T_AVFrame(AVCodecContext *a_codec_ctx);
    ~T_AVFrame();
    virtual enum PixelFormat pix_fmt();
    virtual int width();
    virtual int height();
    virtual uint8_t **data();
    virtual int *linesize();
    AVCodecContext *codecContext();
    AVFrame *frame();
};

class T_AVPicture : public T_AVImage
{
protected:
    AVPicture m_av_picture;
    enum PixelFormat m_pix_fmt;
    int m_width;
    int m_height;
    T_MemoryAligned m_buffer;
public:
    explicit T_AVPicture(PixelFormat a_pix_fmt=PIX_FMT_YUV420P, int a_width=1, int a_height=1);
    explicit T_AVPicture(T_AVImage *a_image);
    ~T_AVPicture();
    virtual enum PixelFormat pix_fmt();
    virtual int width();
    virtual int height();
    virtual uint8_t **data();
    virtual int *linesize();
    void resize(PixelFormat a_pix_fmt, int a_width, int a_height);
    void resizeForQImage(int a_depth, int a_width, int a_height);
    void copyFrom(T_AVImage *a_image);
    void scaleFrom(T_AVImage *a_src, int a_sws_flags = SWS_FAST_BILINEAR);
    QImage toQImage();
protected:
    void p_reallocate(PixelFormat a_pix_fmt, int a_width, int a_height);
};

class T_AVRational
{
public:
    qint64 num; ///< numerator
    qint64 den; ///< denominator
public:
    T_AVRational(AVRational &a_rational)
        : num(a_rational.num)
        , den(a_rational.den)
    {
    }
    T_AVRational operator*(qint64 a) const
    {
        T_AVRational v_result = *this;
        v_result.num *= a;
        return v_result;
    }
    T_AVRational& operator*=(qint64 a)
    {
        this->num *= a;
        return *this;
    }
    T_AVRational operator/(qint64 a) const
    {
        T_AVRational v_result = *this;
        v_result.den *= a;
        return v_result;
    }
    T_AVRational& operator/=(qint64 a)
    {
        this->den *= a;
        return *this;
    }
    qint64 toLongLong() const
    {
        return this->num / this->den;
    }
    double toDouble() const
    {
        return ((double)this->num) / this->den;
    }
};

#endif // T_AVCODEC_H
